from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, update, delete
from sqlalchemy.exc import SQLAlchemyError
from typing import Optional, List
from datetime import datetime
import uuid

from .video_model import VideoTask, TaskStatus
from database.MysqlUtils import get_db_session
from config.logging_config import ProjectLoggers

logger = ProjectLoggers.get_service_logger()

class VideoTaskCRUD:
    """视频任务数据库操作类"""
    
    @staticmethod
    async def create_task(
        original_filename: str,
        user_openid: Optional[str] = None,
        file_size: Optional[int] = None,
        video_format: Optional[str] = None,
        video_url: Optional[str] = None,
        audio_url: Optional[str] = None,
        duration: Optional[float] = None,
        audio_format: Optional[str] = None
    ) -> VideoTask:
        """创建新的视频处理任务"""
        try:
            async with get_db_session() as session:
                task_id = str(uuid.uuid4())
                
                new_task = VideoTask(
                    task_id=task_id,
                    user_openid=user_openid,
                    original_filename=original_filename,
                    file_size=file_size,
                    video_format=video_format,
                    video_url=video_url,
                    audio_url=audio_url,
                    duration=duration,
                    audio_format=audio_format,
                    status=TaskStatus.PENDING.value
                )
                
                session.add(new_task)
                await session.commit()
                await session.refresh(new_task)
                
                logger.info(f"创建视频任务成功: {task_id}")
                return new_task
                
        except SQLAlchemyError as e:
            logger.error(f"创建视频任务失败: {str(e)}")
            raise
    
    @staticmethod
    async def get_task_by_id(task_id: str) -> Optional[VideoTask]:
        """根据任务ID获取任务"""
        try:
            async with get_db_session() as session:
                result = await session.execute(
                    select(VideoTask).where(VideoTask.task_id == task_id)
                )
                return result.scalar_one_or_none()
        except SQLAlchemyError as e:
            logger.error(f"获取视频任务失败 {task_id}: {str(e)}")
            return None
    
    @staticmethod
    async def get_tasks_by_user(user_openid: str) -> List[VideoTask]:
        """获取用户的所有任务"""
        try:
            async with get_db_session() as session:
                result = await session.execute(
                    select(VideoTask)
                    .where(VideoTask.user_openid == user_openid)
                    .order_by(VideoTask.created_at.desc())
                )
                return result.scalars().all()
        except SQLAlchemyError as e:
            logger.error(f"获取用户任务失败 {user_openid}: {str(e)}")
            return []
    
    @staticmethod
    async def update_task_status(
        task_id: str, 
        status: TaskStatus, 
        progress: Optional[int] = None,
        error_message: Optional[str] = None
    ) -> bool:
        """更新任务状态"""
        try:
            async with get_db_session() as session:
                update_data = {
                    'status': status.value,
                    'updated_at': datetime.now()
                }
                
                if progress is not None:
                    update_data['progress'] = progress
                
                if error_message:
                    update_data['error_message'] = error_message
                
                if status == TaskStatus.PROCESSING:
                    update_data['started_at'] = datetime.now()
                elif status in [TaskStatus.COMPLETED, TaskStatus.FAILED]:
                    update_data['completed_at'] = datetime.now()
                
                await session.execute(
                    update(VideoTask)
                    .where(VideoTask.task_id == task_id)
                    .values(**update_data)
                )
                await session.commit()
                
                logger.info(f"更新任务状态成功: {task_id} -> {status.value}")
                return True
                
        except SQLAlchemyError as e:
            logger.error(f"更新任务状态失败 {task_id}: {str(e)}")
            return False
    
    @staticmethod
    async def update_task_urls(
        task_id: str,
        video_url: Optional[str] = None,
        audio_url: Optional[str] = None,
        duration: Optional[float] = None,
        audio_format: Optional[str] = None
    ) -> bool:
        """更新任务的文件URL和相关信息"""
        try:
            async with get_db_session() as session:
                update_data = {'updated_at': datetime.now()}
                
                if video_url:
                    update_data['video_url'] = video_url
                if audio_url:
                    update_data['audio_url'] = audio_url
                if duration:
                    update_data['duration'] = duration
                if audio_format:
                    update_data['audio_format'] = audio_format
                
                await session.execute(
                    update(VideoTask)
                    .where(VideoTask.task_id == task_id)
                    .values(**update_data)
                )
                await session.commit()
                
                logger.info(f"更新任务URL成功: {task_id}")
                return True
                
        except SQLAlchemyError as e:
            logger.error(f"更新任务URL失败 {task_id}: {str(e)}")
            return False
    
    @staticmethod
    async def get_pending_tasks(limit: int = 10) -> List[VideoTask]:
        """获取待处理任务"""
        try:
            async with get_db_session() as session:
                result = await session.execute(
                    select(VideoTask)
                    .where(VideoTask.status == TaskStatus.PENDING.value)
                    .order_by(VideoTask.created_at.asc())
                    .limit(limit)
                )
                return result.scalars().all()
        except SQLAlchemyError as e:
            logger.error(f"获取待处理任务失败: {str(e)}")
            return []
    
    @staticmethod
    async def delete_task(task_id: str) -> bool:
        """删除任务"""
        try:
            async with get_db_session() as session:
                await session.execute(
                    delete(VideoTask).where(VideoTask.task_id == task_id)
                )
                await session.commit()
                
                logger.info(f"删除任务成功: {task_id}")
                return True
                
        except SQLAlchemyError as e:
            logger.error(f"删除任务失败 {task_id}: {str(e)}")
            return False 